//
//  TSCMyAutoCompleteSearchBar.m
//  Tsc_IOS
//
//  Created by Rio on 15-6-1.
//  Copyright (c) 2015年 idream. All rights reserved.
//
// 功能说明：
// 1. 当点击弹出键盘的“搜索”按钮后，自动收回键盘
// 2. 当从table中选择某项后，自动收回键盘
// 3. 如果源数据为空，showTable()将不会显示
// 4. 需要收回键盘时，应该调用该类的resignFirstResponder()方法。不能像MySpinner那样点击屏幕空白区域自动收回

#define ICON_WH 10 // 右侧倒三角的宽高
#define ICON_PADDING 5 // 右侧倒三角距离右边沿的padding
#define TABLE_INIT_H 200 // UITableView的初始高度
#define TABLE_ROW_HEIGHT 30 // UITableView中默认的行高。注：XCODE 6.2中，UITableView不再提供默认的rowHeight


typedef enum {TABLE_UP, TABLE_DOWN} TABLE_UP_OR_DOWN;

#import "TSCMyAutoCompleteSearchBar.h"
#import "TSCMyUtil.h"
#import "TSCConstants.h"
#import "TSCMyUIUtil.h"

@implementation TSCMyAutoCompleteSearchBar {
    UISearchBar * _sb;
    UITableView * _table;
    
    NSMutableArray * _dataArray;
    NSInteger _performingCompletionCount; // 同Android，如果是从table中选择的，则初始为2，并在sb内容变化监听方法中自减1；如果是其他情况（输入的、粘贴的），直接在sb内容变化监听方法中自减1。所以，如果当此值>=1时，表示是从table中选择的（自动补全的）；否则，就是手工输入/粘贴的。
    
}

#pragma mark Getters & Setters

- (NSString *) placeholder {
    return _sb.placeholder;
}

- (void) setPlaceholder:(NSString *)placeholder {
    _sb.placeholder = placeholder;
}

- (NSString *) text {
    return _sb.text;
}

- (void) setText:(NSString *)text {
    _sb.text = text;
}

#pragma mark init

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        
        // 初始化TableView
        [self initUI];
    }
    return self;
}

- (id)init {
    self = [super initWithFrame:CGRectMake(0, 0, 0, 0)];
    if (self) {
        // 初始化TableView
        [self initUI];
    }
    return self;
}

/*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.
 - (void)drawRect:(CGRect)rect
 {
 // Drawing code
 }
 */

/* private */ - (void) initUI {
    
    // ===== 初始化数据源，及标识位
    
    _dataArray = [NSMutableArray array];
    _performingCompletionCount = 0;
    
    // ===== 设置SearchBar
    _sb = [[UISearchBar alloc] init];
    _sb.frame = CGRectMake(0, 0, 0, 0); // 注：初始化时不设置frame，等到设置ac.frame/center/bounds时，再同时设置
    _sb.placeholder = @"TODO"; // 文字左对齐
    _sb.delegate = self; // 注册事件——设置代理
    
    // 添加sb
    [self addSubview:_sb];
    
    // ===== 设置table
    _table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 0, TABLE_INIT_H) style:UITableViewStylePlain]; // 注：初始化时不设置frame，等到设置ac.frame/center/bounds时，再同时设置
    _table.rowHeight = TABLE_ROW_HEIGHT; // 默认行高
    _table.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    _table.scrollEnabled = YES;
    _table.dataSource = self;
    _table.delegate = self;
    _table.backgroundColor = COLOR_TRANSPARENT;
    
}

#pragma mark 设置大小及位置

- (void) setFrame:(CGRect)frame {
    [super setFrame:frame];
    
    // 重新布局UI
    [self relayoutUI];
}

- (void) setCenter:(CGPoint)center {
    [super setCenter:center];
    
    // 重新布局UI
    [self relayoutUI];
}

- (void) setBounds:(CGRect)bounds {
    [super setBounds:bounds];
    
    // 重新布局UI
    [self relayoutUI];
}

// 当使用了setFrame()、setCenter()、setBounds()、或显示table之后，需要重新绘制UI
/* private */ - (void) relayoutUI {
    
    CGRect rf = self.frame; // ac相对于父元素的frame
    CGRect af = [self.superview convertRect:rf toView:[TSCMyUtil getCurrentViewController].view]; // ac相对于窗口的绝对frame
    
    // 绘制sb（相对于ac.frame）
    _sb.frame = CGRectMake(0, 0, rf.size.width, rf.size.height);
    
    // 绘制table（将ac.frame转换为绝对frame）
    if ([self calculateTableDirection] == TABLE_DOWN) {
        _table.frame = CGRectMake(af.origin.x, af.origin.y + af.size.height, af.size.width, _table.frame.size.height);
    } else {
        _table.frame = CGRectMake(af.origin.x, af.origin.y - _table.frame.size.height, af.size.width, _table.frame.size.height);
    }
}

// 设置完数据源后，需要重新设置table高度
/* private */ - (void)resetTabelH {
    
    // ac相对于窗口的绝对frame
    CGRect af = [self.superview convertRect:self.frame toView:[TSCMyUtil getCurrentViewController].view];
    
    // 所有行的总高度
    CGFloat rowsH = _table.rowHeight * [_dataArray count];
    
    // ac上/下边沿距离屏幕底部/顶部的剩余高度
    CGFloat remainScreenH = 0;
    if ([self calculateTableDirection] == TABLE_DOWN) {
        remainScreenH = UI_SCREEN_HEIGHT - (af.origin.y + af.size.height);
    } else {
        remainScreenH = af.origin.y;
    }
    
    // 取3者最小值
    CGFloat tableH = TABLE_INIT_H;
    if (rowsH < tableH) {
        tableH = rowsH;
    }
    if (remainScreenH < tableH) {
        tableH = remainScreenH;
    }
    
    _table.bounds = CGRectMake(0, 0, _table.bounds.size.width, tableH);
    
    // ===== 设置完table高度后，还需要同步更新table的Y值
    
    // 重新获得绝对frame
    af = [self.superview convertRect:self.frame toView:[TSCMyUtil getCurrentViewController].view];
    
    CGFloat tableY = 0;
    if ([self calculateTableDirection] == TABLE_DOWN) {
        tableY = af.origin.y + self.frame.size.height;
    } else {
        tableY = af.origin.y - _table.frame.size.height;
    }
    
    // 重新设置table的位置
    _table.frame = CGRectMake(_table.frame.origin.x, tableY, _table.frame.size.width, _table.frame.size.height);
}


#pragma mark 公共方法

/**
 * 数据准备。完全运行在异步线程中，不涉及UI操作。因为数据准备可能是耗时的。
 *
 * @date 2015-05-25
 * @author Rio
 */
- (void) prepareData_P1:(void (^)())preparingHandler completionHandler:(void (^)())completionHandler {
    // 参数检查
    NSAssert(preparingHandler != nil, @"[E]%s: MyAutoCompleteSearchBar数据准备block为nil！", __FUNCTION__);
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 数据源准备
        // 注：执行之后，应该保证数据源不为nil，且不能没有任何数据项
        preparingHandler();
        
        // 检查数据源是否被正确设置
        //        NSAssert(_dataArray != nil, @"[E]%s: MyAutoCompleteSearchBar设置数据源后，数据源依然为nil！", __FUNCTION__);
        if ([_dataArray count] ==0) {
            NSLog(@"[W]%s: MyAutoCompleteSearchBar设置数据源后，数据源依然没有任何数据！可能影响后续UI显示！", __FUNCTION__);
        }
        
        // 回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            // 设置完数据源后，需要重新设置table高度
            [self resetTabelH];
            
            // 执行回调
            if (completionHandler) {
                completionHandler();
            }
        });
    });
    
}

- (void) cleanData {
    _dataArray = [NSMutableArray array];
}

- (void) applyData {
    [_table reloadData];
}

- (void) showTable {
    // 显示table
    // 注：只有在数据源存在的情况下，才显示
    if ([self isTableShowing] == NO && [_dataArray count] > 0) {
        UIViewController * currentVC = [TSCMyUtil getCurrentViewController];
        [currentVC.view addSubview:_table];
        _table.tag = YES; // 打标记，表示已经被显示
        
        // 重新布局UI
        [self relayoutUI];
    } else {
        if ([self isTableShowing] == YES) {
            NSLog(@"[W]%s: table已经在显示，无需重复显示", __FUNCTION__);
        } else {
            NSLog(@"[W]%s: 数据源为空，无法显示", __FUNCTION__);
        }
    }
    
}

- (void) dismissTable {
    // 移除table
    if ([self isTableShowing] == YES) {
        [_table removeFromSuperview];
        _table.tag = NO; // 打标记，表示已经被关闭
    }
}

- (BOOL) isTableShowing {
    if (_table.tag) {
        return YES;
    } else {
        return NO;
    }
}

- (BOOL) isPerformingCompletion {
    if (_performingCompletionCount >= 1) {
        return YES;
    } else {
        return NO;
    }
}

// 关闭sb的弹出键盘
- (void) resignFirstResponder {
    [_sb resignFirstResponder];
}

- (NSIndexPath *) getSelectedIndexPath {
    return [_table indexPathForSelectedRow];
}

- (id) getSelectedObject {
    NSIndexPath * ip = [self getSelectedIndexPath];
    
    // 注：如果ip为nil不加以判断，将把ip.row作为0，即返回第一个元素。显然这样做时不对的
    if (ip) {
        return [_dataArray objectAtIndex: ip.row];
    } else {
        return nil;
    }
}


#pragma mark 私有方法

// 根据btn在屏幕的位置，计算table应该显示在上方，还是下方
/* private */ - (TABLE_UP_OR_DOWN) calculateTableDirection {
    // 获得ac的绝对center
    // TODO 注：可能得到不正确的结果，因为可能此时ac并没有被添加到vc中，所以绝对位置无法计算！
    //    CGPoint absCenter = [TSCMyUtil getAbsoluteCenter:self];
    CGPoint absCenter = [self.superview convertPoint:self.center toView:[TSCMyUtil getCurrentViewController].view];
    
    if (absCenter.y > (UI_SCREEN_HEIGHT / 2)) {
        return TABLE_UP;
    } else {
        return TABLE_DOWN;
    }
}


#pragma mark UITableView及其代理的生命周期方法

// 获得总行数
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [_dataArray count];
}

// 每一行内容是什么
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    // 如果指定了如何创建cell，则使用自定义cell创建方法
    if (_cellCreator) {
        return _cellCreator(tableView, indexPath);
    } else {
        static NSString *cellReuseId = @"textCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseId];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellReuseId];
            cell.backgroundColor = COLOR_MT_SPINNER_CELL_BG;
        }
        NSUInteger row = [indexPath row];
        NSString * text = [_dataArray objectAtIndex:row];
        if ([text isKindOfClass:[NSString class]] == NO) {
            NSLog(@"[W]%s: MyAutoCompleteSearchBar数据源中，存在不是NSString类型的数据！显示时将抛出异常！数据源中的对象：%@", __FUNCTION__, text);
            
            // 设置为错误提示
            text = @"数据源类型不是NSString！";
        }
        
        cell.textLabel.text = text;
        //    cell.imageView.image = [UIImage imageNamed:@"ic_app_logo_96x96.png"];
        //    cell.detailTextLabel.text = @"详细信息";
        return cell;
    }
}

// 注册事件——选择某行后
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // 打标识：当sb内容变化是因为自动补全导致时，设置为2
    // 注：要比设置sb.text早
    _performingCompletionCount = 2;
    
    // 获得选择的cell字符串内容
    UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath];
    NSString * text = cell.textLabel.text;
    
    // 显示到sb
    _sb.text = text;
    
    // 关闭table
    [self dismissTable];
    
    // 关闭键盘
    [_sb resignFirstResponder];
    
    // item被选中后的回调
    if (_itemSelectedListener) {
        _itemSelectedListener(indexPath);
    }
    
}


#pragma mark SearchBarDelegate

// 注册事件——搜索栏内容变化
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    
    // 将标识位自减1。如果sb内容变化是因为从table中选择导致，则此值之前是2，现在变为1；如果sb内容变化不是从table中选择导致，比如是直接输入，或者粘贴，则此值之前是1或者0，现在变为0或者-1。
    _performingCompletionCount--;
    
    // 如果sb中没有任何内容，则关闭正在显示的table，以防止删空sb后table依然显示
    if ([TSCMyUtil isStringEmpty:searchText] == YES) {
        [self dismissTable];
    }
    
    // 执行回调
    if (_textDidChangeListener) {
        _textDidChangeListener(searchBar, searchText);
    }
}

// 注册事件——点击搜索按钮
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    // 点击搜索按钮后，自动关闭键盘
    [_sb resignFirstResponder];
    
    // 执行回调
    if (_searchBtnClickedListener) {
        _searchBtnClickedListener(searchBar);
    }
}


@end
